﻿using DataProcess.Encryption;
using Microsoft.AspNetCore.Mvc;
using MySqlTool;
using ParkSaleSDK.Adapter;
using ParkSaleSDK.Data;
using ParkSaleSDK.MainSystem;
using ParkSaleSDK.QuickTool;
using System;
using System.Collections.Generic;
using System.Data;
using static APIServer.Controllers.SuUserResponseInfo;
using static SystemSetting.Manangers;
using static SystemSetting.SystemAdapters;

namespace APIServer.Controllers
{
    [Serializable]
    public class SuUserRequestInfo
    {
        public const int s_ChangeValue = 1001, s_AppendValue = 1002, s_DeleteValue = 1003, s_MessageSend = 1004, s_FindValue = 1000, s_Auth = 999, s_Random = 1005;

        public int RequestSignal
        {
            get;
            set;
        }
        public string[] RequestArg
        {
            get;
            set;
        }
        public string Token
        {
            get;
            set;
        }
    }
    [Serializable]
    public class SuUserResponseInfo
    {
        public const int s_Error = -1000, s_BadToken = -1001, OK = 1, s_BadArgs = -1002, s_WrongSignal = -1003;
        public object Body
        {
            get;
            set;
        }
        public int ResponseSignal
        {
            get;
            set;
        }
    }



    [Route("[action]")]
    [ApiController]
    public class SUControllers : ControllerBase
    {
        public static bool TokenAuth(string token)
        {
            token = MD5Coder.MD5Encrypt(token, System.Text.Encoding.UTF8);
            MySqlManager manager = new MySqlManager(Database.Server, Database.UserName, Database.Password, Database.Database, "SuUser", Database.Port);
            var result = manager.Find<Su>($"select * from SuUser where token=\"{token}\"");
            if (result.Count > 0)
                return true;
            else
                return false;
        }
        int ChangeValue(string[] args)
        {
            try
            {
                MySqlManager manager = new MySqlManager(Database.Server, Database.UserName, Database.Password, Database.Database, args[0], Database.Port);
                return manager.Alter(args[1], args[2], args[3]) == 1 ? SuUserResponseInfo.OK : SuUserResponseInfo.s_BadArgs;
            }
            catch(Exception ex)
            {
                return SuUserResponseInfo.s_Error;
            }

        }
        int AppendValue(string[] args)
        {
            try
            {
                MySqlManager manager = new MySqlManager(Database.Server, Database.UserName, Database.Password, Database.Database, args[0], Database.Port);
                List<KeyValuePair<string, string>> ls = new List<KeyValuePair<string, string>>();
                for (int i = 2; i < args.Length; i++)
                {
                    ls.Add(new KeyValuePair<string, string>(args[i], args[++i]));
                }
                return manager.Add(args[1], args[0], manager.Connection, ls.ToArray()) == 1 ? SuUserResponseInfo.OK : SuUserResponseInfo.s_BadArgs;
            }
            catch (Exception ex)
            {
                return SuUserResponseInfo.s_Error;
            }

        }
        int Delete(string[] args)
        {
            try
            {
                MySqlManager manager = new MySqlManager(Database.Server, Database.UserName, Database.Password, Database.Database, args[0], Database.Port);
                return manager.Delete(args[1]) >= 0 ? SuUserResponseInfo.OK : SuUserResponseInfo.s_BadArgs;
            }
            catch
            {
                return SuUserResponseInfo.s_Error;
            }

        }
        public int SendMessage(string[] args)
        {
            var handle = Message[args[0]];

            if (Message[args[0]] == null)
                return s_BadArgs;
            if (handle != null)
            {
                MessageData data = new MessageData() { Content = args[1], Type = args[0], Handled = 0, Time = DateTime.Now, From = args[2], To = args[3], Arg = args[4] };
                w_Message.Append(data);
                return OK;

            }
            else
                return s_BadArgs;
        }
        public DataTable Find(string condition, string table)
        {
            MySqlManager manager = new MySqlManager(Database.Server, Database.UserName, Database.Password, Database.Database, table, Database.Port);
            return manager.Find(condition.Length > 0 ? ParkSaleSDK.QuickTool.SelectStringMaker.MakeSelectStr(table, condition) : ParkSaleSDK.QuickTool.SelectStringMaker.MakeSelectStr(table), table, manager.Connection);
        }
        [Serializable]
        class RowData
        {
            public string Name
            {
                get;
                set;
            }
            public string Value
            {
                get;
                set;
            }
        }
        [Serializable]
        class DatabaseData
        {
            public List<RowData> Detail
            {
                get;
                set;
            }
        }
        Random random = new Random((int)(DateTime.Now.Ticks%9999999));
        public int RandomForOrder(string park)
        {
            MySqlManager manager = new MySqlManager(Database.Server, Database.UserName, Database.Password, Database.Database,c_Order.Table, Database.Port);
            var p= r_Park.Find<Park>(c_Parking.m_id, park);
            if (p.Length > 0)
            {
                try
                {
                    if (p[0].Status == MainSystem.ParkOnSale)
                    {
                        var orders = manager.Find<Order>(SelectStringMaker.MakeSelectStr(c_Order.Table, (c_Order.k_Number, park), (c_Order.k_Status, MainSystem.Order_Pending.ToString())));
                        int su = random.Next(orders.Count);
                        w_Order.Update(orders[su], c_Order.k_Status, MainSystem.Order_NeedToPay.ToString());
                        w_Park.Update(p[0], c_Parking.k_Status, MainSystem.ParkPreOrdered.ToString());
                        for (int i = 0; i < orders.Count; i++)
                        {
                            if (i != su)
                            {
                                w_Order.Update(orders[i], c_Order.k_Status, MainSystem.Order_Closed.ToString());
                            }
                        }
                        return SuUserResponseInfo.OK;
                    }
                }
                catch
                {
                    return SuUserResponseInfo.s_Error;
                }

            }
            return SuUserResponseInfo.s_BadArgs;
        }


        [HttpPost]
        public SuUserResponseInfo Su([FromBody] SuUserRequestInfo request)
        {
            var result = new SuUserResponseInfo() { ResponseSignal = SuUserResponseInfo.s_Error};
            if (TokenAuth(request.Token))
            {
                switch (request.RequestSignal)
                {
                    case SuUserRequestInfo.s_Auth:
                        result.ResponseSignal = SuUserResponseInfo.OK;
                        result.Body = true;
                        break;
                    case SuUserRequestInfo.s_FindValue:
                        if (request.RequestArg.Length != 2)
                        {
                            result.ResponseSignal = SuUserResponseInfo.s_BadArgs;
                        }
                        else
                        {
                            List<DatabaseData> ls = new List<DatabaseData>();
                            var items = Find(request.RequestArg[1], request.RequestArg[0]);
                            int c = items.Columns.Count;
                            foreach (DataRow row in items.Rows)
                            {
                                DatabaseData data = new DatabaseData();
                                data.Detail = new List<RowData>();
                                for (int i = 0; i < c; i++)
                                {
                                    string co = items.Columns[i].ColumnName;
                                    data.Detail.Add(new RowData() { Name = co, Value = row[i].ToString() });
                                }
                                ls.Add(data);
                            }
                            result.Body = ls;
                            result.ResponseSignal = SuUserResponseInfo.OK;
                        }
                        break;
                    case SuUserRequestInfo.s_AppendValue:
                        result.ResponseSignal = AppendValue(request.RequestArg);
                        break;
                    case SuUserRequestInfo.s_ChangeValue:
                        result.ResponseSignal = ChangeValue(request.RequestArg);
                        break;
                    case SuUserRequestInfo.s_DeleteValue:
                        result.ResponseSignal = Delete(request.RequestArg);
                        break;
                    case SuUserRequestInfo.s_MessageSend:
                        result.ResponseSignal = SendMessage(request.RequestArg);
                        break;
                    case SuUserRequestInfo.s_Random:
                        result.ResponseSignal = RandomForOrder(request.RequestArg[0]);
                        break;
                    default:
                        result.ResponseSignal = s_WrongSignal;
                        break;
                }
            }
            else
            {
                if (request.RequestSignal == SuUserRequestInfo.s_Auth)
                {
                    result.ResponseSignal = SuUserResponseInfo.OK;
                    result.Body = false;
                }
                else
                result.ResponseSignal = SuUserResponseInfo.s_BadToken;
            }
            if (result.Body == null)
            {
                result.Body = result.ResponseSignal;
            }
            return result;

        }
    }
}
